SPB Git

Repository Public

route.ts 1.8 KB 44 lines typescript

1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// /api/admin/mail/attachments/[id] — pièce jointe d'un courriel entrant.3// Mêmes règles que le message : propriétaire de la boîte (ou super admin4// pour les non-routés), fichiers hors de /public, nom aléatoire.5import { NextRequest, NextResponse } from "next/server";6import fs from "fs/promises";7import path from "path";8import { getAdminSession } from "@/lib/comms/admin-auth";9import { findMail, canAccessMail, findMailAttachment } from "@/lib/comms/mail";1011const MAIL_UPLOAD_DIR = path.join(process.cwd(), "data", "mail-uploads");1213export async function GET(14  _req: NextRequest,15  { params }: { params: Promise<{ id: string }> },16) {17  const session = await getAdminSession();18  if (!session)19    return NextResponse.json({ error: "Non autorisé." }, { status: 401 });20  const id = Number((await params).id);21  const att = Number.isInteger(id) ? findMailAttachment(id) : undefined;22  const mail = att ? findMail(att.message_id) : undefined;23  if (!att || !mail || !canAccessMail(mail, session.id, session.roles.includes("super_admin")))24    return NextResponse.json({ error: "Fichier introuvable." }, { status: 404 });2526  const safe = path.normalize(att.stored_name).replace(/^(\.\.[/\\])+/, "");27  const full = path.join(MAIL_UPLOAD_DIR, safe);28  if (!full.startsWith(MAIL_UPLOAD_DIR))29    return NextResponse.json({ error: "Chemin refusé." }, { status: 400 });30  let buf: Buffer;31  try {32    buf = await fs.readFile(full);33  } catch {34    return NextResponse.json({ error: "Fichier manquant sur le disque." }, { status: 404 });35  }36  return new NextResponse(new Uint8Array(buf), {37    headers: {38      "Content-Type": att.mime,39      "Content-Disposition": `attachment; filename="${att.original_name.replace(/["\r\n]/g, "")}"`,40      "Cache-Control": "private, no-store",41    },42  });43}44
Files main
Menu

Theme